// 单例模式
// 保证一个类仅有一个是列，并提供一个访问它的全局访问点 （要实现一个标准的单例模式并不复杂，无非是使用一个变量来标志当前是否已经为某个类创建过对象，如果是，则下一次获取当前实例时，直接返回之前创建的对象
/*
    // 实现单例模式
    var Singleton = function(name) {
        // 这里的this指向的是 创建的对象，如果不给instance赋值，那this。instance将一直都是null
        // 这个instance 与 getInstance中的 instance 不是同一个
        this.name = name;
        this.instance = null;
    }

    Singleton.prototype.getName = function() {
        console.log(this.name);
    }

    Singleton.getInstance = function(name) {
        // 这里的this 指向的是Singleton，这个this.instance属性是Singleton的私有属性
        console.log(this.instance);
        if (!this.instance) {
            this.instance = new Singleton(name);
        }

        return this.instance;
    }
 */

/*
    // 这个更好理解 没有牵扯到this的指向，并且采用闭包的形式
    var Singleton = function(name) {
        this.name = name;
    }

    Singleton.getInstance = (function() {
        var instance = null;
        return function(name) {
            if (!instance) {
                instance = new Singleton(name);
            }

            return instance;
        }
    })();

    var a = Singleton.getInstance('sven1');
    var b = Singleton.getInstance('sven2');
    console.log(a, b);
 */
/*
    // 透明的单例模式 （用户从这个类中创建对象的时候，可以想使用其他任何普通类一样）；
    var CreateDiv = (function() {
        var instance;
        var CreateDiv = function(html) {
            if (instance) {
                return instance;
            }
            this.html = html;
            this.init();
            return instance = this;
        }

        CreateDiv.prototype.init = function() {
            var div = document.createElement('div');
            var wrapper = document.querySelector('.part3-wrapper-1');
            div.className = 'wrapper-1-item';
            div.innerHTML = this.html;
            wrapper.appendChild(div)
        }

        return CreateDiv;
    })();

    var a = new CreateDiv('line-1');
    var b = new CreateDiv('line-2');

    console.log(a === b);


    // 在这种单例模式下，一个构造器只能实例化一种对象，当遇到需要用同一个构造器创建多个不同的对象，让其中一些对象成为单例，这个构造器就无法达到目的
    // var CreateDiv = (function() {
    //     var instance;
    //     var CreateDiv = function(tag) {
    //         if (instance) {
    //             return instance
    //         }

    //         this.tag = tag;

    //         // 注意这里的this指向的是构造器创建的对象
    //         return instance = this;
    //     }

    //     CreateDiv.prototype.init = function() {
    //         console.log('init')
    //     }

    //     CreateDiv.prototype.getTagName = function() {
    //         console.log(this.tag)
    //     }

    //     return CreateDiv;
    // })();

    // var div = new CreateDiv('div')
    // div.init(); div.getTagName();
 */

/*
   // 用代理实现单例模式 (使用闭包实例化一个对象，判断对象是否存在，如果存在直接返回这个对象)
   // 这样可以重复使用构造函数，实例化成多个对象，使用代理来获取同一个对象
   var CreateDiv = function(html) {
       this.html = html;
       this.init();
   }

   CreateDiv.prototype.init = function () {
       var div = document.createElement('div');
       var wrapper = document.querySelector('.part3-wrapper-1');
       div.className = 'wrapper-1-item';
       div.innerHTML = this.html;
       wrapper.appendChild(div)
   }

   var proxySingletonCreateDiv = (function() {
       var instance;
       return function(html) {
           if (!instance) {
               instance = new CreateDiv(html);
           }

           return instance;
       }
   })();

   // var a = proxySingletonCreateDiv('html'); // 与使用new 关键字效果相同
   // var b = proxySingletonCreateDiv('div'); // 与使用new 关键字效果相同

   var a = new proxySingletonCreateDiv('html');
   var b = new proxySingletonCreateDiv('div');

   console.log(a, b, a === b);
*/
/*
// javascript中的单例模式
// 单例模式：确保只有一个实例，并提供全局访问。（在javascript中全局变量对象，可以看成一个单例，是一个实例，并可以全局访问，但是全局变量容易命名污染）；
// 降低命名污染的几种方法
    // 1.1. 使用命名空间
    var namespace1 = {
        _value: 'namespace1',
        a: function() {
            console.log('a')
        },

        b: function() {
            console.log('b')
        }
    };

    // 1.2. 动态命名空间
    var MyApp = {};

    MyApp.namespace = function(name) {
        var parts = name.split('.');
        var current = MyApp;
        for (var i in parts) {
            if (!current[parts[i]]) {
                current[parts[i]] = {}
            }

            current = current[parts[i]]
        }
    };

    MyApp.namespace('div.style');
    MyApp.namespace('div.classname');
    MyApp.namespace('div.attr');

    console.log(MyApp)

    // 2.使用闭包封装私有变量
    var user = (function() {
        var __name = 'seven',
            __age = 28;

        return {
            getUserInfo: function() {
                return __name + '-' + __age;
            }
        }
    })();

    console.log(user.getUserInfo());
 */